const { mouse, straightTo } = require('@nut-tree-fork/nut-js');
const { Button } = require('@nut-tree-fork/nut-js');
const { mouseSpeed } = require('@nut-tree-fork/nut-js');
const path = require('path');
const fs = require('fs');
const readline = require('readline');

if (mouseSpeed) {
	mouseSpeed(300);
}

const CONFIG_FILE = path.join(__dirname, 'config.json');

function loadConfig() {
	try {
		if (fs.existsSync(CONFIG_FILE)) {
			const data = fs.readFileSync(CONFIG_FILE, 'utf8');
			return JSON.parse(data);
		}
		return {};
	} catch (e) {
		console.log('⚠️ 配置读取失败:', e.message);
		return {};
	}
}

function ensureConfigDefaults(config) {
	const safe = config && typeof config === 'object' ? { ...config } : {};
	if (!safe.coordinateOffset) safe.coordinateOffset = { offsetX: 0, offsetY: 0 };
	if (!safe.displayConfig) safe.displayConfig = { primaryWidth: 1920, primaryHeight: 1080, isMultiDisplay: false };
	if (!safe.fineTune) safe.fineTune = { enableFineTune: true, stepSize: 20, maxOffset: 1000 };
	if (!Array.isArray(safe.clickPoints)) safe.clickPoints = [];
	return safe;
}

function getArgValue(name, def) {
	const idx = process.argv.findIndex(a => a === `--${name}` || a.startsWith(`--${name}=`));
	if (idx === -1) return def;
	const arg = process.argv[idx];
	if (arg.includes('=')) {
		const val = arg.split('=').slice(1).join('=');
		return val !== undefined && val !== '' ? val : def;
	}
	const next = process.argv[idx + 1];
	if (next && !next.startsWith('--')) return next;
	return def;
}

function getFlag(name, def = false) {
	const idx = process.argv.findIndex(a => a === `--${name}` || a.startsWith(`--${name}=`));
	if (idx === -1) return def;
	const arg = process.argv[idx];
	if (arg.includes('=')) {
		const val = arg.split('=').slice(1).join('=').toLowerCase();
		return val === '1' || val === 'true' || val === 'y' || val === 'yes' || val === '是';
	}
	return true;
}

function prompt(question) {
	return new Promise((resolve) => {
		const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
		rl.question(question, (answer) => { rl.close(); resolve(answer); });
	});
}

async function executeClicks(options) {
	const {
		points,
		cycles = 1,
		perPointClicks = 1,
		delayBetweenClicksMs = 50,
		delayBetweenPointsMs = 200,
		delayBetweenCyclesMs = 500,
		applyOffset = false,
		enableCalibration = false,
		coordinateOffset,
		fineTune,
		logger,
	} = options;

	const log = typeof logger === 'function' ? logger : console.log;

	if (!Array.isArray(points) || points.length === 0) {
		log('⚠️ 没有可点击的坐标');
		return;
	}

	let deltaX = 0;
	let deltaY = 0;
	if (enableCalibration) {
		const first = points[0];
		let x0 = first.x + (applyOffset ? (coordinateOffset.offsetX || 0) : 0);
		let y0 = first.y + (applyOffset ? (coordinateOffset.offsetY || 0) : 0);
		await mouse.move(straightTo({ x: x0, y: y0 }));
		await new Promise(r => setTimeout(r, 100));

		log('\n🎯 快速校准模式');
		log('  W/A/S/D: 1 像素微调，Shift+W/A/S/D: 步长微调');
		log('  Q/回车: 确认, Esc: 跳过');

		readline.emitKeypressEvents(process.stdin);
		if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') { try { process.stdin.setRawMode(true); } catch (_) {} }
		if (typeof process.stdin.resume === 'function') process.stdin.resume();

		await new Promise((resolve) => {
			const onKey = async (str, key) => {
				const name = (key && key.name ? key.name : str).toLowerCase();
				const step = (key && key.shift) ? (fineTune.stepSize || 20) : 1;
				if (name === 'w') deltaY -= step;
				else if (name === 's') deltaY += step;
				else if (name === 'a') deltaX -= step;
				else if (name === 'd') deltaX += step;
				else if (name === 'q' || (key && key.sequence === '\r') || name === 'escape') { resolve(); return; }
				await mouse.move(straightTo({ x: x0 + deltaX, y: y0 + deltaY }));
			};
			process.stdin.on('keypress', onKey);
			log('▶ 等待按键...');
			const cleanup = () => {
				process.stdin.off('keypress', onKey);
				if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') { try { process.stdin.setRawMode(false); } catch (_) {} }
				if (typeof process.stdin.pause === 'function') process.stdin.pause();
			};
			const finalize = () => { cleanup(); resolve(); };
			// finalize 在上面的 resolve 时通过 return 提前结束
		});
	}

	log(`\n🖱️ 开始执行: ${cycles} 轮, 每点点击 ${perPointClicks} 次`);
	for (let c = 1; c <= cycles; c++) {
		log(`\n— 第 ${c}/${cycles} 轮 —`);
		for (let i = 0; i < points.length; i++) {
			const base = points[i];
			let x = base.x + (applyOffset ? (coordinateOffset.offsetX || 0) : 0) + deltaX;
			let y = base.y + (applyOffset ? (coordinateOffset.offsetY || 0) : 0) + deltaY;
			log(`移动到第 ${i + 1} 个点: (${x}, ${y})`);
			await mouse.move(straightTo({ x, y }));
			await new Promise(r => setTimeout(r, 80));

			const isDouble = base && base.mode === 2;
			for (let k = 0; k < perPointClicks; k++) {
				if (isDouble) {
					await mouse.doubleClick(Button.LEFT);
				} else {
					await mouse.leftClick();
				}
				if (k < perPointClicks - 1) await new Promise(r => setTimeout(r, delayBetweenClicksMs));
			}

			if (i < points.length - 1) await new Promise(r => setTimeout(r, delayBetweenPointsMs));
		}
		if (c < cycles) await new Promise(r => setTimeout(r, delayBetweenCyclesMs));
	}
	log('\n✅ 执行完成');
}

async function main() {
	const cfg = ensureConfigDefaults(loadConfig());
	const points = cfg.clickPoints || [];
	if (!points.length) {
		console.log('❌ 未找到已保存的坐标，请先运行 c2.js 录制');
		process.exit(1);
	}

	const cycles = parseInt(getArgValue('cycles', '1'), 10);
	const perPointClicks = parseInt(getArgValue('times', '1'), 10);
	const delayBetweenClicksMs = parseInt(getArgValue('delayClick', '50'), 10);
	const delayBetweenPointsMs = parseInt(getArgValue('delayPoint', '200'), 10);
	const delayBetweenCyclesMs = parseInt(getArgValue('delayCycle', '500'), 10);
	const applyOffset = getFlag('applyOffset', false);
	const enableCalibration = getFlag('calibrate', false);

	console.log('📋 参数:');
	console.log(`  周期: ${cycles}, 每点点击: ${perPointClicks}`);
	console.log(`  间隔: 点击内 ${delayBetweenClicksMs}ms, 点间 ${delayBetweenPointsMs}ms, 轮间 ${delayBetweenCyclesMs}ms`);
	console.log(`  应用全局偏移: ${applyOffset ? '是' : '否'}  快速校准: ${enableCalibration ? '是' : '否'}`);

	await executeClicks({
		points,
		cycles: Number.isFinite(cycles) ? cycles : 1,
		perPointClicks: Number.isFinite(perPointClicks) ? perPointClicks : 1,
		delayBetweenClicksMs: Number.isFinite(delayBetweenClicksMs) ? delayBetweenClicksMs : 50,
		delayBetweenPointsMs: Number.isFinite(delayBetweenPointsMs) ? delayBetweenPointsMs : 200,
		delayBetweenCyclesMs: Number.isFinite(delayBetweenCyclesMs) ? delayBetweenCyclesMs : 500,
		applyOffset,
		enableCalibration,
		coordinateOffset: cfg.coordinateOffset,
		fineTune: cfg.fineTune,
	});
}

module.exports = {
	executeClicks,
	ensureConfigDefaults,
	loadConfig,
};

if (require.main === module) {
	main();
}


